#include "custom_table.h"
#include <cstring>

namespace bytedance_db_project {
CustomTable::CustomTable() {}

CustomTable::~CustomTable() {}

void CustomTable::build_index(T t,int32_t i,int32_t r){
  if(t==NULL){
    t=(T)malloc(sizeof(Tree));
    t->val=i;
    std::vector<int32_t> v;
    v.push_back(r);
    index_.insert(std::unordered_map<int32_t, std::vector<int32_t>>::value_type(i,v));
    return ;
  }
  else if(i > t->val)build_index(t->right,i,r);
  else if(i < t->val)build_index(t->left,i,r);
  else if(i==t->val){
    index_.at(i).push_back(r);
    return ;
  }
}

void CustomTable::Load(BaseDataLoader *loader) {
  // TODO: Implement this!
  index_column_ =0;

  num_cols_ = loader->GetNumCols();
  auto rows = loader->GetRows();
  num_rows_ = rows.size();
  rows_ = new char[FIXED_FIELD_LEN * num_rows_ * num_cols_];
  for (auto row_id = 0; row_id < num_rows_; row_id++) {
    auto cur_row = rows.at(row_id);
    std::memcpy(rows_ + row_id * (FIXED_FIELD_LEN * num_cols_), cur_row,
                FIXED_FIELD_LEN * num_cols_);
  }

  for(auto i=0;i<num_rows_;i++){
    build_index(tree,GetIntField(i,index_column_),i);
  }

}

int32_t CustomTable::GetIntField(int32_t row_id, int32_t col_id) {
  // TODO: Implement this!
  char *p=rows_;
  p+=4*((row_id*num_cols_)+col_id);
  int32_t step;
  std::memcpy(&step,p,4);//内存复制函数、参数分别为目标指针，数据源，复制的字节数
  return step;
}

void CustomTable::PutIntField(int32_t row_id, int32_t col_id, int32_t field) {
  // TODO: Implement this!
  char *p=rows_;
  p+=4*((row_id*num_cols_)+col_id);
  std::memcpy(p,&field,4);
}

int64_t CustomTable::ColumnSum() {
  // TODO: Implement this!
  int64_t sum=0;
  char *p=rows_;
  for(auto i=0;i<num_rows_;i++){
    int32_t step;
    std::memcpy(&step,p,4);
    sum+=step;
    p+=4*num_cols_;
  }
  return sum;
}

int64_t CustomTable::PredicatedColumnSum(int32_t threshold1,
                                         int32_t threshold2) {
  // TODO: Implement this!
  int64_t sum=0;
  for(auto i=0;i<num_rows_;i++){
    int32_t step0,step1,step2;
    step0=GetIntField(i,0);
    step1=GetIntField(i,1);
    step2=GetIntField(i,2);
    if(step1 > threshold1 && step2 < threshold2)sum+=step0;
  }
  return sum;
}

void CustomTable::read_greater_rows(std::vector<int32_t> &vec,int32_t threshold,T t){
  if(t==NULL)return;
  read_greater_rows(vec,threshold,t->left);
  if(t->val > threshold){
    int l=index_.at(t->val).size();
    for(int i=0;i<l;i++){
      vec.push_back(index_.at(t->val)[i]);
    }
  }
  read_greater_rows(vec,threshold,t->right);
}
int64_t CustomTable::PredicatedAllColumnsSum(int32_t threshold) {
  // TODO: Implement this!
  int64_t sum=0;
    std::vector<int32_t> vec;
    T t=tree;
    while(t!=nullptr){
      if(t->val < threshold){
        t=t->right;
      }
      else break;
    }
    read_greater_rows(vec,threshold,t);
    int l=vec.size();
    for(int i=0;i<l;i++){
      for(auto j=0;j<num_cols_;j++){
        sum+=GetIntField(vec[i],j);
      }
    }
    return sum;
}

void CustomTable::read_lower_rows(std::vector<int32_t> &vec,int32_t threshold,T t){
  if(t==NULL)return;
  read_lower_rows(vec,threshold,t->left);
  if(t->val < threshold){
    int l=index_.at(t->val).size();
    for(int i=0;i<l;i++){
      vec.push_back(index_.at(t->val)[i]);
    }
  }
  read_lower_rows(vec,threshold,t->right);
}

int64_t CustomTable::PredicatedUpdate(int32_t threshold) {
  // TODO: Implement this!
  int64_t sum=0;
    std::vector<int32_t> vec;
    T t=tree;
    while(t!=nullptr){
      if(t->val > threshold){
        t=t->left;
      }
      else break;
    }
    read_lower_rows(vec,threshold,t);
    int l=vec.size();
    for(int i=0;i<l;i++){
      int32_t step2=GetIntField(vec[i],2);
      int32_t step3=GetIntField(vec[i],3);
      PutIntField(vec[i],3,step2+step3);
      sum++;
    }
    return sum;
}
} // namespace bytedance_db_project